# coding=utf-8
import time
from jsonpath import jsonpath
from common.assert_operator import *
from common.db import *
from common.utils import Utils

string_assert = string_assert()  # 字符串校验类
pact = Pact()  # 契约校验类
execute_sql = sql()  # sql集合
utils = Utils()


class SmokeBase:
    def approve(self, param, user_login):
        user = param['user']
        response = user_login.goto_Create_Process(user).initiate_submit(param, opinion='发起流程')
        string_assert.eq(response.status_code, 200)
        # 获取发起后的关键信息
        proc_id = jsonpath.jsonpath(response.json(), '$.data.proc_id')[0]
        package_id = jsonpath.jsonpath(response.json(), '$.data.package_id')[0]
        # 数据库查询下一步责任人
        sql = execute_sql.approve_query_sql_by_id(proc_id)
        query_result = sqlserver_query_return_contain_field(sql)
        # query_result长度为1，说明只有列头了，没有查到值了
        while len(query_result) != 1:
            # 获取查询结果，将结果的user列和对应的node列合并成字典，后续进行迭代查询
            users = utils.get_column_value_by_two_array(query_result, '用户code')[0]
            nodes = utils.get_column_value_by_two_array(query_result, '节点GUID')[0]
            # node_user = dict(zip(nodes,users))  #组成{nodeid:user}的字典
            node_user = {nodes: users}
            for node_id, user in node_user.items():
                # 打开审批流程
                kwargs = {'proc_id': proc_id, 'node_id': node_id, 'package_id': package_id}
                process = user_login.goto_Approve_Process(user)
                # 获取tplData的$.ApproveButtons[*].OperationCode，可以得到流程的所有按钮：['Pass', 'RollBack', 'Consult', 'Assigned', 'Terminate', 'Cancel', 'AddSign']
                process_instance_response = process.open_process_instance(**kwargs)
                tpldata = process.get_key_by_process_instance(process_instance_response, 'tpldata')
                rights = jsonpath.jsonpath(tpldata['tpldata'], '$.ApproveButtons[*].OperationCode')  # 获取权限点
                print(f"审批权限：{rights}")
                # 通过proc_id获取流程名称
                process_name = jsonpath.jsonpath(tpldata['tpldata'], '$.ProcessInfo.Title')[0]
                print(f"流程名称：{process_name}")
                # 查询当前待办节点信息
                step_index = utils.get_column_value_by_two_array(query_result, '序号')[0]
                node_index = utils.get_column_value_by_two_array(query_result, '节点序号')[0]
                if step_index == "001" and node_index == "0":  # 第二步进行其他操作
                    # 根据返回的权限，组装匹配的json入参进行审批提交
                    operate = param['second_action']
                    self.approve_action(process, process_instance_response, process_name, user, operate)
                else:
                    self.approve_action(process, process_instance_response, process_name, user)
                # 审批完成后，再通过sql查询下一个审批节点
                query_result = sqlserver_query_return_contain_field(sql)
                approve_after_user = utils.get_column_value_by_two_array(query_result, '用户code')
                times = 0
                # 分流和合流步骤可能由于流程中心程序处理速度比用例慢，导致分流合流步骤未变更状态，10秒内重复查询
                # 自动归档处理时间过长，导致停留在办表中，查询出空user，所以循环查询
                while approve_after_user != False and 'None' in approve_after_user:
                    time.sleep(1)
                    query_result = sqlserver_query_return_contain_field(sql)
                    # query_result长度为1，说明只有列头了，没有查到值了
                    if len(query_result) == 1:
                        break
                    steps = utils.get_column_value_by_two_array(query_result, '步骤名称')
                    approve_after_user = utils.get_column_value_by_two_array(query_result, '用户code')
                    Logger.info(f'第{times + 1}次查询WfProcessInstance表')
                    times += 1
                    if times > 10:
                        assert False, f'{steps}包含了无责任人步骤，无法处理，断言失败！'
                if len(query_result) == 1:  # 如果待办查询结果为空，可能是流程结束了，查询WfProcessInstanceHistory中的流程状态
                    query_history_sql = f"""SELECT ProcessState,ProcessName FROM dbo.WfProcessInstanceHistory WHERE Id = '{proc_id}'"""
                    history_result = sqlserver_query(query_history_sql)
                    times = 0
                    # 循环查下历史表，有可能WfProcessInstance已经处理完没有数据了，但是WfProcessInstanceHistory还没有插入数据，导致没数据
                    while history_result == []:
                        time.sleep(1)
                        history_result = sqlserver_query(query_history_sql)
                        Logger.info(f'第{times + 1}次查询WfProcessInstanceHistory表')
                        times += 1
                        if times > 10:
                            assert False, f'WfProcessInstanceHistory中不存在【{process_name}】,流程id=【{proc_id}】的数据'
                    if history_result:  # 如果流程实例历史表存在数据，说明流程正常审批结束，否则断言错误，因为没有可处理的节点，历史表也没有数据，数据异常了
                        if len(history_result) > 3:
                            assert False, f'同一个流程GUID，历史表存在2条以上的数据'
                        process_status = jsonpath.jsonpath(history_result, '$[0][0]')[0]
                        # process_status = utils.get_field_value_by_two_array(history_result,'ProcessState')[0]
                        if process_status == '4':
                            Logger.info(f"流程：【{process_name}】归档成功")
                        elif process_status == '6':
                            Logger.info(f"流程：【{process_name}】终止成功")
                        elif process_status == '7':
                            Logger.info(f"流程：【{process_name}】作废成功")
                        else:
                            Logger.info(f"流程：【{process_name}】未知状态,流程状态【{process_status}】")
                        assert True
                        break
                    else:
                        assert False, f'【{process_name}】没有可处理的节点，历史表也没有数据，数据异常'

    def approve_action(self, process, process_instance_response, process_name, user, operate=None):
        """
        通过传入operate，开始对应审批：'Pass','Vote', 'RollBack', 'Consult', 'Assigned', 'Terminate', 'Cancel', 'AddSign'
        """
        if operate is None:
            action = process.approval_rights()  # 根据返回的权限，组装匹配的json入参进行审批提交
        else:
            action = operate
        # 得到按钮后，action就能决定进行什么操作
        approve_params = {'process_name': process_name, 'user': user, 'action': action}
        print(approve_params)
        # 如果有分支，有步骤责任人选择，需要调整脚本，不能默认选择
        approve_resp = process.approve_submit(approve_params, process_instance_response)
        string_assert.eq(approve_resp.status_code, 200)
        # 定义契约格式，然后进行契约契约校验
        if action[0] in ["驳回", "作废"]:  # 驳回和终止响应契约格式一样
            contract_format = pact.roll_back_pact_format()
        elif action[0] in ["加签", "终止", "协商", "交办"]:
            contract_format = pact.addsign_pact_format()
        else:
            contract_format = pact.approve_pact_format()
        pact.pact_verify(contract_format, approve_resp.json())
